﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;

namespace Apewer.Models
{

    /// <summary>INI 文件。</summary>
    [Serializable]
    public sealed class IniFile : IEnumerable<IniSection>, IToJson
    {

        List<IniSection> _sections = new List<IniSection>();

        #region Constructors

        /// <summary></summary>
        public IniFile() { }

        /// <summary></summary>
        public IniFile(IEnumerable<IniSection> sections)
        {
            if (sections == null) throw new ArgumentNullException(nameof(sections));
            sections.ForEach(Add);
        }

        #endregion

        #region CRUD

        /// <summary>节的数量。</summary>
        public int Count { get => _sections.Count; }

        /// <summary>添加节。</summary>
        public void Add(IniSection section)
        {
            if (section == null) return;
            _sections.Add(section);
        }

        /// <summary>添加节。</summary>
        public void Add(string name, TextField[] fields) => _sections.Add(new IniSection(name, fields));

        /// <summary>获取节。</summary>
        public IniSection Get(string sectionName)
        {
            var emptyName = sectionName.IsEmpty();
            foreach (var section in _sections)
            {
                if (emptyName)
                {
                    if (section.Name.IsEmpty()) return section;
                }
                else
                {
                    if (section.Name == sectionName) return section;
                }
            }
            return null;
        }

        /// <summary>移除节。</summary>
        public void Remove(IniSection section)
        {
            while (_sections.Contains(section)) _sections.Remove(section);
        }

        /// <summary>移除节。</summary>
        public void Remove(string sectionName)
        {
            var emptyName = sectionName.IsEmpty();
            foreach (var section in _sections)
            {
                if (emptyName)
                {
                    _sections = _sections.FindAll(x => x.Name.IsEmpty());
                }
                else
                {
                    _sections = _sections.FindAll(x => x.Name == sectionName);
                }
            }
        }

        #endregion

        #region IEnumerable<IniSection>

        /// <summary></summary>
        public IEnumerator<IniSection> GetEnumerator() => new Enumerator<IniSection>(i => i < _sections.Count ? new Class<IniSection>(_sections[i]) : null);

        IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();

        #endregion

        #region IToJson

        /// <summary></summary>
        public Json ToJson()
        {
            var json = Json.NewArray();
            _sections.ForEach(section => json.AddItem(section.ToJson()));
            return json;
        }

        #endregion

        #region ToString

        const string CRLF = "\r\n";

        /// <summary></summary>
        public override string ToString() => ToString(CRLF);

        /// <summary></summary>
        public string ToString(string seperator)
        {
            if (seperator.IsEmpty()) seperator = CRLF;

            var sb = new StringBuilder();

            var noName = 0;
            foreach (var section in _sections)
            {
                if (section == null) continue;

                if (section.Name.IsEmpty())
                {
                    var count = section.Count;
                    for (var i = 0; i < count; i++)
                    {
                        var field = section.GetField(i);
                        if (Append(sb, field))
                        {
                            sb.Append(seperator);
                            noName += 1;
                        }
                    }
                }

            }
            if (noName > 1) sb.Append(seperator);

            foreach (var section in _sections)
            {
                if (section == null) continue;

                if (section.Name.NotEmpty())
                {
                    sb.Append("[");
                    sb.Append(section.Name);
                    sb.Append("]");
                    sb.Append(seperator);

                    foreach (var field in section)
                    {
                        if (Append(sb, field))
                        {
                            sb.Append(seperator);
                        }
                    }
                }
                sb.Append(seperator);
            }

            return sb.ToString();
        }

        static bool Append(StringBuilder sb, TextField field)
        {
            var nameEmpty = field.Name.IsEmpty();
            var valueEmpty = field.Value.IsEmpty();
            if (nameEmpty && valueEmpty) return false;

            if (!nameEmpty)
            {
                sb.Append(field.Name);
                sb.Append(" =");
            }

            if (!valueEmpty)
            {
                if (nameEmpty) sb.Append("; ");
                else sb.Append(" ");
                sb.Append(field.Value);
            }

            return true;
        }

        #endregion

    }

}
